using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using WindowsPhoneEssentials.Abstractions;

namespace WindowsPhoneEssentials.Testing.Abstractions
{
    public class MemoryIsolatedStorageFile : IIsolatedStorageFile
    {
        private readonly Dictionary<string, MemoryStream> store = new Dictionary<string, MemoryStream>();

        public void Dispose()
        { }

        public long Quota { get; set; }

        public long AvailableFreeSpace { get; set; }

        public void Remove()
        {
            store.Clear();
        }

        public bool IncreaseQuotaTo(long newQuotaSize)
        {
            Quota = newQuotaSize;
            return true;
        }

        public void DeleteFile(string file)
        {
            if (store.ContainsKey(file))
                store.Remove(file);
        }

        public bool FileExists(string path)
        {
            return store.ContainsKey(path);
        }

        public bool DirectoryExists(string path)
        {
            throw new NotSupportedException("Not yet, ask if you need it quick");
        }

        public void CreateDirectory(string dir)
        {
            throw new NotSupportedException("Not yet, ask if you need it quick");
        }

        public void DeleteDirectory(string dir)
        {
            throw new NotSupportedException("Not yet, ask if you need it quick");
        }

        public string[] GetFileNames()
        {
            return store.Keys.ToArray();
        }

        public string[] GetFileNames(string searchPattern)
        {
            throw new NotSupportedException("Not yet, ask if you need it quick");
        }

        public string[] GetDirectoryNames()
        {
            throw new NotSupportedException("Not yet, ask if you need it quick");
        }

        public string[] GetDirectoryNames(string searchPattern)
        {
            throw new NotSupportedException("Not yet, ask if you need it quick");
        }

        public Stream OpenFile(string path, FileMode mode)
        {
            return OpenFile(path, mode, FileAccess.ReadWrite);
        }

        public Stream OpenFile(string path, FileMode mode, FileAccess access)
        {
            return OpenFile(path, mode, access, FileShare.None);
        }

        public Stream OpenFile(string path, FileMode mode, FileAccess access, FileShare share)
        {
            MemoryStream memoryStream;
            switch (mode)
            {
                case FileMode.CreateNew:
                case FileMode.Create:
                    DeleteFile(path);
                    memoryStream = new MemoryStream();
                    store.Add(path, memoryStream);
                    return memoryStream;
                case FileMode.Open:
                    if (store.ContainsKey(path))
                        return Restore(store[path]);
                    throw new FileNotFoundException(path + " not found");
                case FileMode.Append:
                case FileMode.OpenOrCreate:
                    if (store.ContainsKey(path))
                        return Restore(store[path]);
                    memoryStream = new MemoryStream();
                    store.Add(path, memoryStream);
                    return memoryStream;
                case FileMode.Truncate:
                    DeleteFile(path);
                    memoryStream = new MemoryStream();
                    store.Add(path, memoryStream);
                    return memoryStream;
                default:
                    throw new ArgumentOutOfRangeException("mode");
            }
        }

        private static Stream Restore(MemoryStream ms)
        {
            return new MemoryStream(ms.ToArray());
        }

        public Stream CreateFile(string path)
        {
            return OpenFile(path, FileMode.Create);
        }
    }
}